﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

public abstract class GeneralUICanvas : MonoBehaviour
{
	/// <summary>
	/// <para>所有通用UI元素管理类共用的Canvas</para>
	/// </summary>
	protected static Canvas _generalCanvas = null;

	/// <summary>
	/// <para>获取所有通用UI元素管理类共用的Canvas</para>
	/// </summary>
	public static Canvas GetCanvas()
	{
		return GeneralUICanvas._generalCanvas;
	}

	public static void DestroySelf()
	{
		if (_generalCanvas != null)
			GameObject.Destroy(_generalCanvas.gameObject);
	}

	#region 显示顺序

	protected enum Priority
	{
		Currency,
		Lowest,
		Common,
		Tutorial,
		Log,
	}

	/// <summary>
	/// <para>通用UI元素管理类的渲染优先级，值小的先渲染</para>
	/// </summary>
	Priority _priority;

	/// <summary>
	/// <para>虚函数，通用UI元素管理类通过该函数返回自己的渲染优先级</para>
	/// </summary>
	protected abstract Priority GetPriority();

	/// <summary>
	/// <para>设置渲染优先级</para>
	/// </summary>
	protected void SetPriority(Priority priority)
	{
		_priority = priority;
		RefreshChildren();
	}

	/// <summary>
	/// <para>设置渲染优先级后刷新所有通用UI元素管理类</para>
	/// </summary>
	void RefreshChildren()
	{
		int uiCount = transform.parent.childCount;
		for (int i = 0; i < uiCount - 1; i++) {
			for (int j = 0; j < uiCount - 1 - i; j++) {
				Transform cur = transform.parent.GetChild(j);
				Transform next = transform.parent.GetChild(j + 1);
				if (cur.GetComponent<GeneralUICanvas>()._priority > next.GetComponent<GeneralUICanvas>()._priority) {
					cur.SetSiblingIndex(j + 1);
				}
			}
		}
	}

	#endregion
}

/// <summary>
/// <para>通用UI元素的基础类，可用于如教学、弹出框、日志等通用UI元素。</para>
/// <para>通用UI元素管理类建立时继承该类，其都会在同一个通用Canvas下建立UI元素</para>
/// </summary>
public abstract class GeneralUIManager<T> : GeneralUICanvas where T : GeneralUIManager<T>
{
	/// <summary>
	/// <para>静态单例对象</para>
	/// </summary>
	static T _instance = null;

	/// <summary>
	/// <para>创建静态单例对象</para>
	/// </summary>
	public static T Instance {
		get {
			if (_instance == null) {
				GameObject go = new GameObject();
				_instance = go.AddComponent<T>();
				go.name = _instance.GetType().ToString();
				_instance.AddToUIManager();
				_instance.SetPriority(_instance.GetPriority());
				_instance.Init();
			}
			return _instance;
		}
	}

	protected virtual void Init()
	{
		Debug.Log(this.GetType().ToString() + " init.");
	}

	/// <summary>
	/// <para>管理类销毁时销毁静态单例对象</para>
	/// </summary>
	void OnDestory()
	{
		_instance = null;
	}

	/// <summary>
	/// <para>将通用UI元素管理类的挂到共用的Canvas下作为子物体，如该Canvas不存在，则先创建之</para>
	/// </summary>
	void AddToUIManager()
	{
		if (GeneralUICanvas._generalCanvas == null) {
			var go = new GameObject(typeof(GeneralUICanvas).ToString());

			GeneralUICanvas._generalCanvas = go.AddComponent<Canvas>();
			GeneralUICanvas._generalCanvas.renderMode = RenderMode.ScreenSpaceOverlay;
			GeneralUICanvas._generalCanvas.sortingOrder = 10;

			var canvasScaler = go.AddComponent<CanvasScaler>();
			canvasScaler.uiScaleMode = CanvasScaler.ScaleMode.ScaleWithScreenSize;
			canvasScaler.referenceResolution = UIUtils._CanvasResolution;
			canvasScaler.screenMatchMode = CanvasScaler.ScreenMatchMode.Expand;

			var raycaster = go.AddComponent<GraphicRaycaster>();
			raycaster.enabled = true;

			DontDestroyOnLoad(go);
		}

		transform.SetParent(GeneralUICanvas._generalCanvas.transform, false);
		transform.localPosition = Vector3.zero;
		transform.localScale = Vector3.one;
		transform.SetAsFirstSibling();

		StartCoroutine(ReviseRectSize());
	}

	/// <summary>
	/// <para>延时一帧调整RectTransform的尺寸，因为如果在创建的那一帧设置，可能会被Unity的自动设置覆盖</para>
	/// </summary>
	IEnumerator ReviseRectSize()
	{
		yield return null;

		var rectTrans = gameObject.GetComponent<RectTransform>();
		if (rectTrans == null)
			rectTrans = gameObject.AddComponent<RectTransform>();
		rectTrans.sizeDelta = (transform.parent as RectTransform).sizeDelta;
	}
}
